<!DOCTYPE html>
<html lang="zh-CN">
<head hexo-theme='https://github.com/volantis-x/hexo-theme-volantis/tree/4.1.5'>
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
    
  
  <!-- 渲染优化 -->
  <meta http-equiv='x-dns-prefetch-control' content='on' />
  <link rel='dns-prefetch' href='https://cdn.jsdelivr.net'>
  <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  <!-- 页面元数据 -->
  
  <title>论文阅读-Hawk.The Blockchain Model of Cryptography and Privacy-Preserving Smart Contracts - Schenk - Blog</title>
  
    <meta name="keywords" content="blockchain">
  

  
    <meta name="description" content="论文 Hawk.The Blockchain Model of Cryptography and Privacy-Preserving Smart Contracts阅读笔记">
  

  <!-- feed -->
  

  <!-- import meta -->
  

  <!-- link -->
  
    <link rel="shortcut icon" type='image/x-icon' href="https://cdn.jsdelivr.net/gh/Schenk75/Source/logos/steroids.svg">
  

  <!-- import link -->
  

  
    
<link rel="stylesheet" href="/css/first.css">

  

  
  <link rel="stylesheet" href="/css/style.css" media="print" onload="this.media='all';this.onload=null">
  <noscript><link rel="stylesheet" href="/css/style.css"></noscript>
  

  <script id="loadcss"></script>

</head>

<body>
  

<header id="l_header" class="l_header auto shadow blur floatable show" style='opacity: 0' >
  <div class='container'>
  <div id='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h m-phone' id="pjax-header-nav-list">
        <li><a id="s-comment" class="fas fa-comments fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
          <li><a id="s-toc" class="s-toc fas fa-list fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
            <img no-lazy class='logo' src='https://cdn.jsdelivr.net/gh/Schenk75/Source@latest/logos/taiga.svg'/>
          
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h m-pc'>
          
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>

      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fas fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>

			<ul class='switcher nav-list-h m-phone'>
				
					<li><a class="s-search fas fa-search fa-fw" target="_self" href='javascript:void(0)'></a></li>
				
				<li>
          <a class="s-menu fas fa-bars fa-fw" target="_self" href='javascript:void(0)'></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>
		</div>
	</div>
  </div>
</header>

  <div id="l_body">
    <div id="l_cover">
  
    
        <div id="full" class='cover-wrapper post dock' style="display: none;">
          
            <div class='cover-bg lazyload placeholder' data-bg="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/interstellar.jpg"></div>
          
          <div class='cover-body'>
  <div class='top'>
    
    
      <p class="title">Schenk - Blog</p>
    
    
      <p class="subtitle">SJTUer | Cuber</p>
    
  </div>
  <div class='bottom'>
    <div class='menu navigation'>
      <div class='list-h'>
        
          
            <a href="/categories/"
              
              
              id="categories">
              <i class='fas fa-folder-open fa-fw'></i><p>分类</p>
            </a>
          
            <a href="/tags/"
              
              
              id="tags">
              <i class='fas fa-tags fa-fw'></i><p>标签</p>
            </a>
          
            <a href="/archives/"
              
              
              id="archives">
              <i class='fas fa-archive fa-fw'></i><p>归档</p>
            </a>
          
            <a href="/friends/"
              
              
              id="friends">
              <i class='fas fa-link fa-fw'></i><p>友链</p>
            </a>
          
            <a href="/about/"
              
              
              id="about">
              <i class='fas fa-info-circle fa-fw'></i><p>关于</p>
            </a>
          
        
      </div>
    </div>
  </div>
</div>

          <div id="scroll-down" style="display: none;"><i class="fa fa-chevron-down scroll-down-effects"></i></div>
        </div>
    
  
  </div>

    <div id='safearea'>
      <div class='body-wrapper' id="pjax-container">
        

<div class='l_main'>
  <article class="article post white-box reveal md shadow floatable article-type-post" id="post" itemscope itemprop="blogPost">
  


  
  <div class="article-meta" id="top">
    
    
    
      <h1 class="title">
        论文阅读-Hawk.The Blockchain Model of Cryptography and Privacy-Preserving Smart Contracts
      </h1>
      <div class='new-meta-box'>
        
          
            
<div class='new-meta-item author'>
  <a class='author' href="/" rel="nofollow">
    <img no-lazy src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/avatar.jpg">
    <p>Schenk</p>
  </a>
</div>

          
        
          
            
  <div class='new-meta-item category'>
    <a class='notlink'>
      <i class="fas fa-folder-open fa-fw" aria-hidden="true"></i>
      <a class="category-link" href="/categories/Paper-Reading/">Paper Reading</a>
    </a>
  </div>


          
        
          
            <div class="new-meta-item date" itemprop="dateUpdated" datetime="2022-07-20T11:52:41+08:00">
  <a class='notlink'>
    <i class="fas fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：2022年7月20日</p>
  </a>
</div>

          
        
          
            
  <div class="new-meta-item wordcount">
    <a class='notlink'>
      <i class="fas fa-keyboard fa-fw" aria-hidden="true"></i>
      <p>字数：5.1k字</p>
    </a>
  </div>
  <div class="new-meta-item readtime">
    <a class='notlink'>
      <i class="fas fa-hourglass-half fa-fw" aria-hidden="true"></i>
      <p>时长：18分钟</p>
    </a>
  </div>


          
        
          
            
  <div class="new-meta-item browse leancloud">
    <a class='notlink'>
      
      <div id="lc-pv" data-title="论文阅读-Hawk.The Blockchain Model of Cryptography and Privacy-Preserving Smart Contracts" data-path="/2021/06/06/paper-reading/paper-hawk/">
        <i class="fas fa-eye fa-fw" aria-hidden="true"></i>
        <span id='number'><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span>
        次浏览
      </div>
    </a>
  </div>


          
        
      </div>
    
  </div>


  
  <h2 id="1-引入">1.引入</h2>
<p>区块链上的可信时钟的存在对于协议中实现公平交易至关重要：恶意用户可能会过早地中止协议以避免资金支付，但是有了可信时钟，过早地中止协议会被判定为超时，这样区块链就可以将恶意用户的抵押存款重新分配给诚实用户，以此来惩罚恶意用户。</p>
<p>尽管区块链和智能合约具有表现力和强大功能，但这些技术目前缺乏交易隐私：尽管各方可以创建匿名公钥以增加其匿名性，但每个匿名公钥的所有交易和余额都是公开可见的。缺乏隐私是去中心化智能合约广泛应用的主要障碍，因为一些金融交易，如保险合同或股票交易，被许多个人和组织视为高度机密。</p>
<h3 id="Hawk概览">Hawk概览</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210603123101742.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210603123101742.png" srcset="" alt="image-20210603123101742"></p>
<p>Hawk编译器负责将程序编译成区块链和用户之间的加密协议，一个Hawk程序包括两个部分：</p>
<ul>
<li>隐私部分 $\phi_{priv}$ ： 用于接收各方的输入数据和货币等，并执行计算来分配收益。$\phi_{priv}$用于保护参与者的数据和资金交换；</li>
<li>公开部分 $\phi_{pub}$ ：不涉及隐私数据和资金的部分。</li>
</ul>
<p>Hawk编译器把Hawk程序编译成以下几个部分，这些部分共同定义了用户、管理员和区块链之间的加密协议：</p>
<ul>
<li>被所有共识节点执行的区块链程序</li>
<li>由用户执行的程序</li>
<li>由管理员（一个特别协助方）执行的程序</li>
</ul>
<h4 id="安全保证">安全保证</h4>
<ol>
<li><strong>链上隐私</strong>：只有合约双方自愿公开信息，区块链才会将交易隐私向公众公布，$\phi_{priv}$以加密形式展现在公众眼前。非正式地讲，链上隐私的实现通过向区块链发送“加密”信息，并依靠零知识证明来确保合同执行和资金保存的正确性。</li>
<li><strong>合约安全</strong>：保护同一合约协议中的各方互不侵犯，不仅包括机密性和真实性等密码学概念，还包括存在欺骗和中止行为时的公平交易</li>
</ol>
<h4 id="最低限度信任管理员">最低限度信任管理员</h4>
<p>Hawk合约的执行由管理员推动，管理员可以看到用户的输入，并被信任不会泄露用户的隐私数据。</p>
<ul>
<li>管理员不是可信第三方：即使管理员可以任意偏离协议或与当事人串通，管理员也不能影响合约的正确执行，如果管理员中止了协议，就会受到经济上的惩罚，而用户则会得到相应的补偿；</li>
<li>管理人员不需要被信任来维护基础货币的安全性或隐私，如防止双花攻击等；</li>
<li>如果多个合约实例同时运行，则每个合约可以指定不同的管理员，而恶意管理员只会影响该实例；</li>
<li>可以用可信计算硬件实例化管理员，或使用用户自己之间的多方计算代替。</li>
</ul>
<h3 id="实例：密封拍卖">实例：密封拍卖</h3>
<p>该实例用于实现一个密封的、第二价格的拍卖，其中出价最高的竞标者获胜，但支付第二高的价格，且竞标者在不知道其他人的出价的情况下提交出价。</p>
<p>该实例中$\phi_{priv}$决定中标者和支付金额；$\phi_{pub}$使用公共存款来防止管理员通过中止协议来损害竞标者利益。</p>
<h4 id="合约的安全需求">合约的安全需求</h4>
<p>前提：</p>
<ul>
<li>Hawk的安全建立在区块链本身的安全特性上：假设区块链的共识协议在对手不拥有大量计算能力的情况下是安全的；</li>
<li>在Hawk中，为了减少链上执行代码产生的费用，设计的协议在链下执行大部分计算</li>
</ul>
<p>安全需求：</p>
<ul>
<li><strong>独立隐私输入</strong>：各用户在提交自己的投注资金之前无法查看其他用户的投注金额，即使与恶意管理员串通也无法查看；</li>
<li><strong>交易后隐私保护</strong>：只要管理员不公布信息，即使在拍卖之后各用户的出价也不会公布；</li>
<li><strong>公平交易</strong>：拍卖参与者可能试图提早退出协议，以避免付款或影响资金再分配。如果一方中止或拍卖管理员中止，中止方将受到经济惩罚，而其余方则获得补偿。Hawk在特定超时后强制执行退款；</li>
<li><strong>防范不诚实管理员</strong>：除了中止协议外，不诚实的管理员不能影响拍卖结果和资金再分配。对于中止协议的管理员，对其进行罚款。</li>
</ul>
<h4 id="中止和超时">中止和超时</h4>
<p>该实例定义了三种超时 $T_1&lt;T_2&lt;T_3$：</p>
<ul>
<li>$T_1$：Hawk合约在$T_1$之后停止招标；</li>
<li>$T_2$：所有用户都需要在$T_2$内向管理员公布自己的出价，否则将视作0；</li>
<li>$T_3$：如果管理员中止协议，用户可以在$T_3$后收回投标资金。</li>
</ul>
<p>$\phi_{pub}$实现额外的激励机制，本实例中如果管理员提前中止拍卖，将重新分配管理员的公共存款。</p>
<h3 id="本文贡献">本文贡献</h3>
<p>Hawk是第一个在去中心化加密货币系统中同时提供隐私交易和可编程性的系统：</p>
<ul>
<li><strong>去中心化智能合约的正式模型</strong>：针对密码学的区块链模型，提出了一种形式化的通用可组合性(UC)模型，这种形式模型是独立的，并且在区块链模型中定义协议的安全性时通常是有用的；</li>
<li><strong>新的加密套件</strong>：实现了一个新的加密套件，它将私有事务与可编程逻辑绑定在一起，包含三个基本原语 <em>freeze</em>，<em>compute</em> 和 <em>finalize</em> ：
<ul>
<li><em>freeze</em>原语允许各方提交正常数据以及货币，提交的货币在合约中冻结，支付分配在之后由$\phi_{priv}$确定；</li>
<li><em>compute</em>的过程中，各方将提交的数据和货币向管理员公开，以便管理员计算$\phi_{priv}$函数，根据$\phi_{priv}$的结果，管理员构造新的私有货币支付给各用户。然后，管理员向区块链提交新的私有货币以及它们的零知识证明。此时之前冻结的货币在用户中重新分配。</li>
</ul>
</li>
<li><strong>实现和评估</strong>：创建Hawk原型，实现一些应用来评估性能。提出协议优化，得到10倍性能。在约有100个参与方时，管理员使用四核进行密码计算（协议中最昂贵的部分），时间在2.85分钟内；所有的链上计算（由矿工执行）都十分便宜，都在20毫秒以内。</li>
</ul>
<h2 id="2-密码学的区块链模型">2.密码学的区块链模型</h2>
<h3 id="区块链模型">区块链模型</h3>
<p>区块链在正确性和可用性方面受到信任，但在隐私方面不受信任。区块链不仅维护一个存储每个假名账户余额的全局账本，而且还执行用户定义的程序。论文给出了区块链的通用模型，可以运行任意图灵完备程序：</p>
<ul>
<li>区块链的时钟是离散的，每一轮用 <code>round</code> 或 <code>epoch</code> 表示</li>
<li>所有链上用户都可以观察到区块链的状态，包括公共账本和任何用户定义的程序</li>
<li>发送到区块链的消息将在下一轮开始时到达。在同一轮中，敌手可以任意重新排序发送到区块链的消息，但不能丢弃消息，然而敌手可以在链下丢弃各方之间传递的消息。这意味着敌手可能会尝试抢先攻击（例如当观察到一个诚实用户正在交易一只股票时，对手会通过发送交易同一只股票的竞争交易来抢占先机）</li>
<li>用户在区块链上可以创建任意多的假名账户</li>
<li>假设区块链将正确执行任何规定好的计算</li>
</ul>
<h3 id="区块链正式建模">区块链正式建模</h3>
<p>论文提供了正式的、精确的功能规范和安全性规范，并且设计的协议在通用可组合性(UC)框架下正式证明是安全的。</p>
<p>建模的程序分为理想程序（记为$IdealP$）、区块链程序（记为$B$）和用户/管理员程序（记为$UserP$）。同时论文定义包装器来将伪代码程序转换为UC框架下的程序：</p>
<ul>
<li>理想包装器$F(·)$将理想程序$IdealP$转换为理想函数$F(IdealP)$</li>
<li>区块链包装器$G(·)$将区块链程序$B$转换为区块链函数$G(B)$，可以延迟区块链上的消息在下一轮开始到达</li>
<li>协议包装器$\Pi(·)$将用户/管理员程序$UserP$转换为用户端或管理员端的协议$\Pi(UserP)$</li>
</ul>
<p>包装器还实现了智能合约应用的一些共同特征，包括时间、公共账本、假名和敌手对消息重新排序，这样就不需要为每个区块链应用重复这些符号。</p>
<h4 id="正式UC建模及证明">正式UC建模及证明</h4>
<p>附录B</p>
<h3 id="编程约定">编程约定</h3>
<ul>
<li><strong>Timer激活点</strong>：理想函数包装器$F(·)$和区块链包装器$G(·)$实现了逐轮递增的时钟，并且每次时钟增加，包装器就会调用<strong>Timer</strong>激活点。因此理想程序和区块链程序可以定义<strong>Timer</strong>激活点来实现超时操作；</li>
<li><strong>理想程序中的延迟处理</strong>：在灰色背景中编写的程序指令表示的是不会立即进行的计算，而是推迟到下一轮开始时执行。这是一种简写，因为在实际协议中，区块链函数完成的任何计算都将被延迟；</li>
<li><strong>假名</strong>：在理想程序、区块链程序和用户端程序中出现的所有表示用户的标识符默认情况下都指假名；</li>
<li><strong>账本和转账</strong>：$符号仅用于可读性（用于区分与货币相关的变量和其他变量），并没有特殊含义。</li>
</ul>
<h2 id="3-密码学抽象">3.密码学抽象</h2>
<p>论文使用理想程序的形式来描述密码学抽象。Hawk实现了以下规范：</p>
<ul>
<li>私人账本和转账：定义理想程序$IdealP_{cash}$来描述私人账本的需求；</li>
<li>Hawk-specific原语：定义 <em>freeze</em>、<em>compute</em> 和 <em>finalize</em> 三种Hawk-specific原语来同时满足交易隐私性和可编程性。</li>
</ul>
<h3 id="隐私资金规范-IdealP-cash">隐私资金规范$IdealP_{cash}$</h3>
<img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210604135946524.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210604135946524.png" srcset="" alt="image-20210604135946524" style="zoom:80%;" />
<h4 id="Mint">Mint</h4>
<p><code>mint</code> 操作允许用户 $P$ 将资金从他的公共总账 $ledger[P]$ 转移到私有货币池 $Coins[P]$ ，每次转账后用户 $P$ 的私有货币被创建，并与一个值 $val$ 关联。</p>
<p>为保证安全性，$IdealP_{cash}$ 在用户 $P$ 创建私有货币之前检查他的公共总账 $ledger[P]$ 中的余额是否足够。</p>
<h4 id="Pour">Pour</h4>
<p><code>pour</code> 操作允许用户 $P$ 私下在其私人货币池花钱。简单起见，采用两种输入货币和两种输出货币来模拟货币交换。</p>
<p>为保证安全性，$IdealP_{cash}$ 会检查：</p>
<ul>
<li>对于两种输入货币，用户 $P$ 确实拥有其声明的量那么多的私有货币</li>
<li>两种输入货币的总价值和两种输出货币的总价值相等</li>
</ul>
<h4 id="隐私">隐私</h4>
<p>当诚实用户 $P$ 执行 <code>mint</code> 操作时，敌手 $A$ 能获得 $(P, val)$。对于公共货币池的任何操作都会被敌手 $A$ 获得。</p>
<p>当诚实用户 $P$ 执行 <code>pour</code> 操作时，敌手 $A$ 只能获得动态生成的输出假名 $P_1$ 和 $P_2$ ，而不知道哪种在私人池的货币被花了，也不知道花钱的人是谁。如果恶意用户是 <code>pour</code> 操作的接收方，那他会额外获得货币的金额。</p>
<h4 id="额外的微妙之处">额外的微妙之处</h4>
<ul>
<li>诚实用户会跟踪一个装有不同货币的钱包，每当诚实用户执行 <code>pour</code> 操作时，首先会检查本地钱包中是否有相同的货币，如果有，会立即将货币从钱包中取出，通过这种方式，如果诚实用户在一轮中进行了多次 <code>pour</code> 操作，将为每次 <code>pour</code> 操作选择不同的货币；</li>
<li>诚实用户在下一轮之前是不能花掉同一轮中自己获得的货币的，但是恶意用户可以（因为任何消息都立即被敌手获得，敌手也可以为区块链在同一轮中收到的所有消息选择排序方式）</li>
<li>诚实用户总会 <code>pour</code> 给存在的假名，但敌手可以 <code>pour</code> 给不存在的假名 $\bot$ ，这种情况下私人货币实际上进入了一个黑洞，并且无法取回。</li>
</ul>
<h3 id="Hawk规范-IdealP-Hawk">Hawk规范$IdealP_{Hawk}$</h3>
<img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210604151820907.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210604151820907.png" srcset="" alt="image-20210604151820907" style="zoom:70%;" />
<img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210604151900011.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210604151900011.png" srcset="" alt="image-20210604151900011" style="zoom:70%;" />
<h4 id="Freeze">Freeze</h4>
<p>用户 $P$ 从私有货币池 $Coins$ 中移除一种货币，并将其添加到 $FrozenCoins$ 中进行冻结，用户的私有输入 $in$ 也会记录在 $FrozenCoins$ 中。$IdealP_{Hawk}$ 检查 $P$ 之前没有调用过 <em>freeze</em>，并且货币 $(P, val)$ 存在在 $Coins$ 中。</p>
<h4 id="Compute">Compute</h4>
<p>用户 $P$ 调用 <em>compute​</em> 时，其私有输入 $in$ 和冻结的货币 $val$ 将公开给管理员 $P_M$</p>
<h4 id="Finalize">Finalize</h4>
<p>管理员 $P_M$ 提交一个公共输入 $in_M$ 到 $IdealP_{Hawk}$ ，$IdealP_{Hawk}$ 根据所有用户的输入和冻结的货币价值计算 $\phi_{priv}$ 的结果，并根据这个结果重新分配 $FrozenCoins$ 。为了保证安全，$IdealP_{Hawk}$ 检查冻结货币的总价值等于输出货币的总价值。</p>
<h4 id="与公共合约交互">与公共合约交互</h4>
<p>$IdealP_{Hawk}$ 的功能由公共Hawk合约 $\phi_{pub}$ 参数化，在 <em>finalize</em> 过程中，$IdealP_{Hawk}$ 调用 $\phi_{pub}.check$ 。$\phi_{pub}$ 的作用如下：</p>
<ul>
<li>检查管理员的输入 $in_M$ 的格式是否正确</li>
<li>重新分配公共存款：如果用户或管理员提前中止协议，或者用户提供了无效的资金投入（例如少于最低赌注），$\phi_{pub}$ 可以重新分配用户的公开存款</li>
</ul>
<h4 id="安全和隐私需求">安全和隐私需求</h4>
<ul>
<li>当诚实用户 $P$ <em>freeze</em> 冻结一笔金额时，敌手不能看到该金额，但能看到诚实用户的假名 $P$ 。这不会损害诚实用户的隐私，因为他可以随时创建新的假名；</li>
<li>当诚实用户调用 <em>compute</em> 时，只有管理员 $P_M$ 能看到用户的输入 和冻结的金额，其他用户不能看到；</li>
<li>在 <em>finalize</em> 操作期间，输出 $out$ 会公开该所有用户，如果不希望公开，$out$ 可以为空。</li>
</ul>
<h4 id="时间和中止">时间和中止</h4>
<p><em>freeze</em> 操作在 $T_1$ 内完成，$compute$ 操作在 $T_2$ 内完成，如果用户冻结了货币但是在 $T_2$ 内没有公布，则这些冻结的货币会丢失，即 $(in_i, val_i):=(0, \bot)$</p>
<h4 id="简化的假设">简化的假设</h4>
<ul>
<li>论文实现的协议不支持管理员中止协议时冻结货币的退款</li>
<li>假设参与合约的假名集和超时 $T_1, T_2$ 硬编码在程序中</li>
</ul>
<h2 id="4-加密协议">4.加密协议</h2>
<p>协议分为两部分：</p>
<h3 id="隐私资金转移">隐私资金转移</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210605154609219.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210605154609219.png" srcset="" alt="image-20210605154609219"></p>
<p>区块链程序 $Blockchain_{cash}$ 维护一系列私有货币 $Coins$ ，每一种货币的形式为 $(P, coin:=Comm_s($val))$ ，其中 $P$ 是用户假名，$coin$ 是根据随机数 $s$ 生成的货币值 $$val$ 的承诺。</p>
<p>在 <code>pour</code> 操作期间，用户 $P$ 选择两种 $Coins$ 中的货币来花费，分别为 $(P, coin_1)$ 和 $(P, coin_2)$ 。<code>pour</code> 操作将 $val^{‘}_1$ 和 $val^{’}_2$ 分别付给两个输出假名 $P_1$ 和 $P_2$ ，并且保证 $val_1+val_2=val<sup>{'}_1+val</sup>{‘}<em>2$ 。支付用户选择新的随机数 $s_i^{'}(i\in{1,2})$ 并计算输出货币 $(P_i,coin_i:=Comm</em>{s<sup>{'}_i}($val_i</sup>{’}))$ ，支付用户将 $s_i^{‘}$ 和 $val_i^{’}$ 发送给收款用户 $P_i$ 。发送者计算一个零知识证明来证明输出的货币是适当构造的，其中正确性涉及以下方面：</p>
<ul>
<li>货币的存在性：$(P, coin_1)$ 和 $(P, coin_2)$ 确实是私有货币池 $Coins$ 的一部分，这里使用零知识证明可以确保支付用户隐藏其花费的货币种类。为了提高效率，$Blockchain_{cash}$ 维护一个 $Coins$ 的Merkle树 $MT$ 来证明货币的存在性；</li>
<li>不会双重支付：每一个货币 $(P, coin)$ 都有一个唯一的序列号 $sn$ ，在 <code>pour</code> 货币时，必须提供货币的 $sn$ 以及其零知识证明来证明 $sn$ 的正确性，$Blockchain_{cash}$ 确保 $sn$ 不会被用两次；</li>
<li>保护金额：零知识证明确保输入的货币和输出的货币的总价值相等。</li>
</ul>
<p>当诚实用户向诚实用户 <code>pour</code> 时，敌手 $A$ 不会知道承诺方案 $Comm$ 隐藏的输出货币的值，敌手 $A$ 可以看到接收两种输出货币的用户假名；</p>
<p>当不诚实用户 $P^<em>$ 向诚实用户 $P$ <code>pour</code> 时，尽管敌手知道 $coin$ 公开，然而一旦交易在$Blockchain_{cash}$生效，敌手就不能使用 $(P,coin)$，因为 $P^</em>$ 不知道 $P$ 的密钥。</p>
<blockquote>
<p>PRF：伪随机函数</p>
<p>ENC：加密</p>
<p>DEC：解密</p>
</blockquote>
<h3 id="同时实现隐私和可编程逻辑">同时实现隐私和可编程逻辑</h3>
<img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210605154651192.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-hawk/image-20210605154651192.png" srcset="" alt="image-20210605154651192" style="zoom:70%;" />
<h4 id="Freeze-v2">Freeze</h4>
<p><em>freeze</em> 操作不直接向用户支出，而是将资金以及附带的隐私输入提交给智能合约，这是使用类似<code>pour​</code>的协议完成的：</p>
<ul>
<li>用户 $P$ 选择一个私有货币 $(P,coin)\in Coins$，其中 $coin:=Comm_s($val)$。$P$使用自己的密钥计算 $coin$ 的序列号 $sn$ 并公开，用于防止双重支付；</li>
<li>用户 $P$ 计算承诺 $(val||in||k)$ ，其中 $in$ 是用户输入，$k$ 是一个对称加密密钥（用于实际优化）；</li>
<li>用户 $P$ 进行零知识证明，类似 <code>pour</code> 操作。</li>
</ul>
<h4 id="Compute-v2">Compute</h4>
<p><em>compute</em> 操作在链下计算 ${val_i^{‘}}_{i\in[n]}$以及进行正确性证明。Hawk依赖管理员 $P_M$ 来进行计算，所有用户将自己的输入经过管理员的公钥加密后发送给管理员：$ct:=ENC(P_M.epk,r,($val||in||k||s^{’}))$ ，其中 $ct$ 是密文， $P_M.epk$ 是管理员的公钥。</p>
<p>在获取用户的公开信息后，管理员通过私有合约 $\phi_{priv}$ 计算 ${val_i^{'}}_{i\in[n]}$ 以及公开输出 $out$。管理员同时也会构建一个零知识证明来证明结果。</p>
<h4 id="Finalize-v2">Finalize</h4>
<p>管理员提交$\phi_{priv}$的结果以及零知识证明到$Blockchain_{cash}$之后，$Blockchain_{cash}$验证证明并重新分配冻结的资金，与此同时还将管理员的公开输入 $in_M$ 和公开输出 $out$ 发送给公开Hawk合约 $\phi_{pub}$。</p>
<h4 id="定理1">定理1</h4>
<p>假设Merkle树使用的哈希算法是抗碰撞的，承诺方案 $Comm$ 是 perfectly binding 和计算隐藏的，零知识证明的NIZK方案满足零知识需求，加密方案ENC和SENC是正确并且安全的，PRF方案是安全的，则协议 $UserP_{cash}$ 和 $UserP_{hawk}$ 安全地模拟了静态模型中抵抗恶意对手的理想功能$F(IdealP_{hawk})$ 。</p>
<blockquote>
<p>证明在文献[37]:<br>
A. Kosba, A. Miller, E. Shi, Z. Wen, and C. Papamanthou. Hawk:<br>
The blockchain model of cryptography and privacy-preserving smart<br>
contracts. <a target="_blank" rel="noopener" href="http://ia.cr/2015/675">http://ia.cr/2015/675</a>.</p>
</blockquote>
<h3 id="扩展和讨论">扩展和讨论</h3>
<h4 id="使用可信硬件实例化管理员">使用可信硬件实例化管理员</h4>
<p>使用可信硬件SGX实例化管理员从而在安全秘密地进行链下计算。但是<strong>任何不与区块链交互的链下协议都不能在中止的情况下提供公平交易——即使使用了可信硬件</strong>。</p>
<h2 id="5-在UC协议中采用SNARKS以及实际优化">5.在UC协议中采用SNARKS以及实际优化</h2>
<h3 id="在UC协议中采用SNARKS">在UC协议中采用SNARKS</h3>
<p>简洁非交互式知识论证（Succinct Non-interactive ARguments of Knowledge）对一般计算任务进行了简洁的证明，并已在多个系统中实现。</p>
<p>论文的UC协议实现采用高效的SNARK-lifting转换。</p>
<h3 id="实际考虑">实际考虑</h3>
<h4 id="高效SNARK电路">高效SNARK电路</h4>
<p>一个SNARK证明器的性能主要取决于代数电路中乘法门的数量，为了更高效，论文通过两种方式设计优化电路：</p>
<ol>
<li>使用SNARK友好的密码原语</li>
<li>构建定制的电路生成器来友好地实现SNARK，而不是依赖编译器来编译更高级别的实现</li>
</ol>
<p>Hawk中在主要的密码学构造块包括：针对Merkle树的抗碰撞哈希函数、伪随机函数、承诺和加密。在实现中，模数q被设置为底层SNARK实现的254位素数，维数d在80位的安全级别下设置为3，在112位的安全级别下设置为4。</p>
<p>更多性能优化略。。。</p>
<h2 id="6-实现和评估">6.实现和评估</h2>
<p>略</p>

  
  
    
    <div class='footer'>
      
      
      
      
    </div>
  
  
    


  <div class='article-meta' id="bottom">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date">
  <a class='notlink'>
    <i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i>
    <p>发布于：2021年6月6日</p>
  </a>
</div>

        
      
        
          
  
  <div class="new-meta-item meta-tags"><a class="tag" href="/tags/blockchain/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>blockchain</p></a></div>


        
      
    </div>
  </div>


  
  

  
    <div class="prev-next">
      
        <a class='prev' href='/2021/06/13/paper-reading/paper-Ekiden/'>
          <p class='title'><i class="fas fa-chevron-left" aria-hidden="true"></i>论文阅读-Ekiden. A Platform for Confidentiality-Preserving, Trustworthy, and Performant Smart Contracts</p>
          <p class='content'>1.引入
现有的智能合约系统因此缺乏保密性和隐私性，它们不能安全地存储或计算敏感数据；区块链共识需求也使得智能合约在计算能力、存储容量和事务吞吐量方面的性能低下。
区块链和TEE有互补特性：

...</p>
        </a>
      
      
        <a class='next' href='/2021/04/15/learning-notes/substrate%E5%85%A5%E9%97%A8/'>
          <p class='title'>Substrate入门<i class="fas fa-chevron-right" aria-hidden="true"></i></p>
          <p class='content'>Start
架构

substrate客户端的基本构成：

存储(storage)：存储区块链的状态，使用简单而高效的键值对存储机制
运行时(Runtime)：定义处理块的逻辑，包括状态转换逻辑...</p>
        </a>
      
    </div>
  
</article>


  

  






</div>
<aside class='l_side'>
  
  
    
    



  <section class="widget toc-wrapper shadow floatable desktop mobile" id="toc-div" >
    
  <header>
    
      <i class="fas fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E5%BC%95%E5%85%A5"><span class="toc-text">1.引入</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Hawk%E6%A6%82%E8%A7%88"><span class="toc-text">Hawk概览</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%89%E5%85%A8%E4%BF%9D%E8%AF%81"><span class="toc-text">安全保证</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9C%80%E4%BD%8E%E9%99%90%E5%BA%A6%E4%BF%A1%E4%BB%BB%E7%AE%A1%E7%90%86%E5%91%98"><span class="toc-text">最低限度信任管理员</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%9E%E4%BE%8B%EF%BC%9A%E5%AF%86%E5%B0%81%E6%8B%8D%E5%8D%96"><span class="toc-text">实例：密封拍卖</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%90%88%E7%BA%A6%E7%9A%84%E5%AE%89%E5%85%A8%E9%9C%80%E6%B1%82"><span class="toc-text">合约的安全需求</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%AD%E6%AD%A2%E5%92%8C%E8%B6%85%E6%97%B6"><span class="toc-text">中止和超时</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9C%AC%E6%96%87%E8%B4%A1%E7%8C%AE"><span class="toc-text">本文贡献</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E5%AF%86%E7%A0%81%E5%AD%A6%E7%9A%84%E5%8C%BA%E5%9D%97%E9%93%BE%E6%A8%A1%E5%9E%8B"><span class="toc-text">2.密码学的区块链模型</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8C%BA%E5%9D%97%E9%93%BE%E6%A8%A1%E5%9E%8B"><span class="toc-text">区块链模型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8C%BA%E5%9D%97%E9%93%BE%E6%AD%A3%E5%BC%8F%E5%BB%BA%E6%A8%A1"><span class="toc-text">区块链正式建模</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%AD%A3%E5%BC%8FUC%E5%BB%BA%E6%A8%A1%E5%8F%8A%E8%AF%81%E6%98%8E"><span class="toc-text">正式UC建模及证明</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BC%96%E7%A8%8B%E7%BA%A6%E5%AE%9A"><span class="toc-text">编程约定</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E5%AF%86%E7%A0%81%E5%AD%A6%E6%8A%BD%E8%B1%A1"><span class="toc-text">3.密码学抽象</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%9A%90%E7%A7%81%E8%B5%84%E9%87%91%E8%A7%84%E8%8C%83-IdealP-cash"><span class="toc-text">隐私资金规范$IdealP_{cash}$</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Mint"><span class="toc-text">Mint</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Pour"><span class="toc-text">Pour</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9A%90%E7%A7%81"><span class="toc-text">隐私</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%A2%9D%E5%A4%96%E7%9A%84%E5%BE%AE%E5%A6%99%E4%B9%8B%E5%A4%84"><span class="toc-text">额外的微妙之处</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Hawk%E8%A7%84%E8%8C%83-IdealP-Hawk"><span class="toc-text">Hawk规范$IdealP_{Hawk}$</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Freeze"><span class="toc-text">Freeze</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Compute"><span class="toc-text">Compute</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Finalize"><span class="toc-text">Finalize</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%8E%E5%85%AC%E5%85%B1%E5%90%88%E7%BA%A6%E4%BA%A4%E4%BA%92"><span class="toc-text">与公共合约交互</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%89%E5%85%A8%E5%92%8C%E9%9A%90%E7%A7%81%E9%9C%80%E6%B1%82"><span class="toc-text">安全和隐私需求</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%97%B6%E9%97%B4%E5%92%8C%E4%B8%AD%E6%AD%A2"><span class="toc-text">时间和中止</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%AE%80%E5%8C%96%E7%9A%84%E5%81%87%E8%AE%BE"><span class="toc-text">简化的假设</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-%E5%8A%A0%E5%AF%86%E5%8D%8F%E8%AE%AE"><span class="toc-text">4.加密协议</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%9A%90%E7%A7%81%E8%B5%84%E9%87%91%E8%BD%AC%E7%A7%BB"><span class="toc-text">隐私资金转移</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%8C%E6%97%B6%E5%AE%9E%E7%8E%B0%E9%9A%90%E7%A7%81%E5%92%8C%E5%8F%AF%E7%BC%96%E7%A8%8B%E9%80%BB%E8%BE%91"><span class="toc-text">同时实现隐私和可编程逻辑</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Freeze-v2"><span class="toc-text">Freeze</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Compute-v2"><span class="toc-text">Compute</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Finalize-v2"><span class="toc-text">Finalize</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%9A%E7%90%861"><span class="toc-text">定理1</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%A9%E5%B1%95%E5%92%8C%E8%AE%A8%E8%AE%BA"><span class="toc-text">扩展和讨论</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E5%8F%AF%E4%BF%A1%E7%A1%AC%E4%BB%B6%E5%AE%9E%E4%BE%8B%E5%8C%96%E7%AE%A1%E7%90%86%E5%91%98"><span class="toc-text">使用可信硬件实例化管理员</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-%E5%9C%A8UC%E5%8D%8F%E8%AE%AE%E4%B8%AD%E9%87%87%E7%94%A8SNARKS%E4%BB%A5%E5%8F%8A%E5%AE%9E%E9%99%85%E4%BC%98%E5%8C%96"><span class="toc-text">5.在UC协议中采用SNARKS以及实际优化</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9C%A8UC%E5%8D%8F%E8%AE%AE%E4%B8%AD%E9%87%87%E7%94%A8SNARKS"><span class="toc-text">在UC协议中采用SNARKS</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%9E%E9%99%85%E8%80%83%E8%99%91"><span class="toc-text">实际考虑</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%AB%98%E6%95%88SNARK%E7%94%B5%E8%B7%AF"><span class="toc-text">高效SNARK电路</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-%E5%AE%9E%E7%8E%B0%E5%92%8C%E8%AF%84%E4%BC%B0"><span class="toc-text">6.实现和评估</span></a></li></ol>
    </div>
  </section>


  


</aside>



        
        
          <!--此文件用来存放一些不方便取值的变量-->
<!--思路大概是将值藏到重加载的区域内-->

<script>
  window.pdata={}
  pdata.ispage=true;
  pdata.postTitle="论文阅读-Hawk.The Blockchain Model of Cryptography and Privacy-Preserving Smart Contracts";
  pdata.commentPath="";
  pdata.commentPlaceholder="";

  var l_header=document.getElementById("l_header");
  
  l_header.classList.add("show");
  
</script>

        
      </div>
      
  
  <footer class="footer clearfix">
    <br><br>
    
      
        <div class='copyright'>
        <p><a target="_blank" rel="noopener" href="https://github.com/Schenk75/Schenk75.github.io">Copyright © 2020-2022 Schenk</a></p>

        </div>
      
    
  </footer>


      <a id="s-top" class="fas fa-arrow-up fa-fw" href='javascript:void(0)'></a>
    </div>
  </div>
  <div>
    <script>
window.volantis={};
window.volantis.loadcss=document.getElementById("loadcss");
/********************脚本懒加载函数********************************/
function loadScript(src, cb) {
var HEAD = document.getElementsByTagName('head')[0] || document.documentElement;
var script = document.createElement('script');
script.setAttribute('type','text/javascript');
if (cb) script.onload = cb;
script.setAttribute('src', src);
HEAD.appendChild(script);
}
//https://github.com/filamentgroup/loadCSS
var loadCSS = function( href, before, media, attributes ){
	var doc = window.document;
	var ss = doc.createElement( "link" );
	var ref;
	if( before ){
		ref = before;
	}
	else {
		var refs = ( doc.body || doc.getElementsByTagName( "head" )[ 0 ] ).childNodes;
		ref = refs[ refs.length - 1];
	}
	var sheets = doc.styleSheets;
	if( attributes ){
		for( var attributeName in attributes ){
			if( attributes.hasOwnProperty( attributeName ) ){
				ss.setAttribute( attributeName, attributes[attributeName] );
			}
		}
	}
	ss.rel = "stylesheet";
	ss.href = href;
	ss.media = "only x";
	function ready( cb ){
		if( doc.body ){
			return cb();
		}
		setTimeout(function(){
			ready( cb );
		});
	}
	ready( function(){
		ref.parentNode.insertBefore( ss, ( before ? ref : ref.nextSibling ) );
	});
	var onloadcssdefined = function( cb ){
		var resolvedHref = ss.href;
		var i = sheets.length;
		while( i-- ){
			if( sheets[ i ].href === resolvedHref ){
				return cb();
			}
		}
		setTimeout(function() {
			onloadcssdefined( cb );
		});
	};
	function loadCB(){
		if( ss.addEventListener ){
			ss.removeEventListener( "load", loadCB );
		}
		ss.media = media || "all";
	}
	if( ss.addEventListener ){
		ss.addEventListener( "load", loadCB);
	}
	ss.onloadcssdefined = onloadcssdefined;
	onloadcssdefined( loadCB );
	return ss;
};
</script>
<script>
  
  loadCSS("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.14/css/all.min.css", window.volantis.loadcss);
  
  
  
  
</script>
<!-- required -->

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5/dist/jquery.min.js"></script>

<script>
  function pjax_fancybox() {
    $(".md .gallery").find("img").each(function () { //渲染 fancybox
      var element = document.createElement("a"); // a 标签
      $(element).attr("class", "fancybox");
      $(element).attr("pjax-fancybox", "");  // 过滤 pjax
      $(element).attr("href", $(this).attr("src"));
      if ($(this).attr("data-original")) {
        $(element).attr("href", $(this).attr("data-original"));
      }
      $(element).attr("data-fancybox", "images");
      var caption = "";   // 描述信息
      if ($(this).attr('alt')) {  // 判断当前页面是否存在描述信息
        $(element).attr('data-caption', $(this).attr('alt'));
        caption = $(this).attr('alt');
      }
      var div = document.createElement("div");
      $(div).addClass("fancybox");
      $(this).wrap(div); // 最外层套 div ，其实主要作用还是 class 样式
      var span = document.createElement("span");
      $(span).addClass("image-caption");
      $(span).text(caption); // 加描述
      $(this).after(span);  // 再套一层描述
      $(this).wrap(element);  // 最后套 a 标签
    })
    $(".md .gallery").find("img").fancybox({
      selector: '[data-fancybox="images"]',
      hash: false,
      loop: false,
      closeClick: true,
      helpers: {
        overlay: {closeClick: true}
      },
      buttons: [
        "zoom",
        "close"
      ]
    });
  };
  function SCload_fancybox() {
    if ($(".md .gallery").find("img").length == 0) return;
    loadCSS("https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css", document.getElementById("loadcss"));
    setTimeout(function() {
      loadScript('https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js', pjax_fancybox)
    }, 1);
  };
  $(function () {
    SCload_fancybox();
  });
</script>


<!-- internal -->







  <script defer src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script>
<script>
  // https://www.npmjs.com/package/vanilla-lazyload
  // Set the options globally
  // to make LazyLoad self-initialize
  window.lazyLoadOptions = {
    elements_selector: ".lazyload",
    threshold: 0
  };
  // Listen to the initialization event
  // and get the instance of LazyLoad
  window.addEventListener(
    "LazyLoad::Initialized",
    function (event) {
      window.lazyLoadInstance = event.detail.instance;
    },
    false
  );
  document.addEventListener('DOMContentLoaded', function () {
    lazyLoadInstance.update();
  });
  document.addEventListener('pjax:complete', function () {
    lazyLoadInstance.update();
  });
</script>




  
  
    <script>
      window.FPConfig = {
        delay: 0,
        ignoreKeywords: [],
        maxRPS: 5,
        hoverDelay: 25
      };
    </script>
    <script defer src="https://cdn.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"></script>
  




  <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
    var clipboard = new ClipboardJS('.btn-copy', {
        target: function (trigger) {
            return trigger.nextElementSibling
        }
    });
    function wait(callback, seconds) {
        var timelag = null;
        timelag = window.setTimeout(callback, seconds)
    }
    function pjax_initCopyCode() {
		if($(".highlight .code pre").length+$(".article pre code").length==0)return;
        var copyHtml = '';
        copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
        copyHtml += '<i class="fas fa-copy"></i><span>COPY</span>';
        copyHtml += '</button>';
        $(".highlight .code pre").before(copyHtml);
        $(".article pre code").before(copyHtml);
        clipboard.off('success').on('success', function (e) {
            let $btn = $(e.trigger);
            $btn.addClass('copied');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-check-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPIED';
            wait(function () {
                $icon.removeClass('fa-check-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        });
        clipboard.off('error').on('error', function (e) {
            e.clearSelection();
            let $btn = $(e.trigger);
            $btn.addClass('copy-failed');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-times-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPY FAILED';
            wait(function () {
                $icon.removeClass('fa-times-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        })
    }
    $(function () {
        pjax_initCopyCode()
    });
</script>










  <script defer src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/tools/busuanzi.pure.mini.js" data-pjax></script>


  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/app.min.js"></script>




  
  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/search.min.js"></script>

  


<!-- optional -->

  <script>
const SearchServiceimagePath="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@master/img/";
const ROOT =  ("/" || "/").endsWith('/') ? ("/" || "/") : ("//" || "/" );
function listenSearch(){
  
    customSearch = new HexoSearch({
      imagePath: SearchServiceimagePath
    });
  
}
document.addEventListener("DOMContentLoaded", listenSearch);

</script>











  <script defer>

  const LCCounter = {
    app_id: 'u9j57bwJod4EDmXWdxrwuqQT-MdYXbMMI',
    app_key: 'jfHtEKVE24j0IVCGHbvuFClp',
    custom_api_server: '',

    // 查询存储的记录
    getRecord(Counter, url, title) {
      return new Promise(function (resolve, reject) {
        Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({url})))
          .then(resp => resp.json())
          .then(({results, code, error}) => {
            if (code === 401) {
              throw error;
            }
            if (results && results.length > 0) {
              var record = results[0];
              resolve(record);
            } else {
              Counter('post', '/classes/Counter', {url, title: title, times: 0})
                .then(resp => resp.json())
                .then((record, error) => {
                  if (error) {
                    throw error;
                  }
                  resolve(record);
                }).catch(error => {
                console.error('Failed to create', error);
                reject(error);
              });
            }
          }).catch((error) => {
          console.error('LeanCloud Counter Error:', error);
          reject(error);
        });
      })
    },

    // 发起自增请求
    increment(Counter, incrArr) {
      return new Promise(function (resolve, reject) {
        Counter('post', '/batch', {
          "requests": incrArr
        }).then((res) => {
          res = res.json();
          if (res.error) {
            throw res.error;
          }
          resolve(res);
        }).catch((error) => {
          console.error('Failed to save visitor count', error);
          reject(error);
        });
      });
    },

    // 构建自增请求体
    buildIncrement(objectId) {
      return {
        "method": "PUT",
        "path": `/1.1/classes/Counter/${ objectId }`,
        "body": {
          "times": {
            '__op': 'Increment',
            'amount': 1
          }
        }
      }
    },

    // 校验是否为有效的 UV
    validUV() {
      var key = 'LeanCloudUVTimestamp';
      var flag = localStorage.getItem(key);
      if (flag) {
        // 距离标记小于 24 小时则不计为 UV
        if (new Date().getTime() - parseInt(flag) <= 86400000) {
          return false;
        }
      }
      localStorage.setItem(key, new Date().getTime().toString());
      return true;
    },

    addCount(Counter) {
      var enableIncr = '' === 'true' && window.location.hostname !== 'localhost';
      enableIncr = true;
      var getterArr = [];
      var incrArr = [];
      // 请求 PV 并自增
      var pvCtn = document.querySelector('#lc-sv');
      if (pvCtn || enableIncr) {
        var pvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-sv', 'Visits').then((record) => {
          incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-sv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + 1;
              if (pvCtn) {
                pvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(pvGetter);
      }

      // 请求 UV 并自增
      var uvCtn = document.querySelector('#lc-uv');
      if (uvCtn || enableIncr) {
        var uvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-uv', 'Visitors').then((record) => {
          var vuv = this.validUV();
          vuv && incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-uv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + (vuv ? 1 : 0);
              if (uvCtn) {
                uvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(uvGetter);
      }

      // 请求文章的浏览数，如果是当前页面就自增
      var allPV = document.querySelectorAll('#lc-pv');
      if (allPV.length > 0 || enableIncr) {
        for (i = 0; i < allPV.length; i++) {
          let pv = allPV[i];
          let title = pv.getAttribute('data-title');
          var url = 'http://example.com' + pv.getAttribute('data-path');
          if (url) {
            var viewGetter = this.getRecord(Counter, url, title).then((record) => {
              // 是当前页面就自增
              let curPath = window.location.pathname;
              if (curPath.includes('index.html')) {
                curPath = curPath.substring(0, curPath.lastIndexOf('index.html'));
              }
              if (pv.getAttribute('data-path') == curPath) {
                incrArr.push(this.buildIncrement(record.objectId));
              }
              if (pv) {
                var ele = pv.querySelector('#lc-pv #number');
                if (ele) {
                  if (pv.getAttribute('data-path') == curPath) {
                    ele.innerText = (record.times || 0) + 1;
                  } else {
                    ele.innerText = record.times || 0;
                  }
                  pv.style.display = 'inline';
                }
              }
            });
            getterArr.push(viewGetter);
          }
        }
      }

      // 如果启动计数自增，批量发起自增请求
      if (enableIncr) {
        Promise.all(getterArr).then(() => {
          incrArr.length > 0 && this.increment(Counter, incrArr);
        })
      }

    },


    fetchData(api_server) {
      var Counter = (method, url, data) => {
        return fetch(`${ api_server }/1.1${ url }`, {
          method,
          headers: {
            'X-LC-Id': this.app_id,
            'X-LC-Key': this.app_key,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      this.addCount(Counter);
    },

    refreshCounter() {
      var api_server = this.app_id.slice(-9) !== '-MdYXbMMI' ? this.custom_api_server : `https://${ this.app_id.slice(0, 8).toLowerCase() }.api.lncldglobal.com`;
      if (api_server) {
        this.fetchData(api_server);
      } else {
        fetch('https://app-router.leancloud.cn/2/route?appId=' + this.app_id)
          .then(resp => resp.json())
          .then(({api_server}) => {
            this.fetchData('https://' + api_server);
          });
      }
    }

  };

  LCCounter.refreshCounter();

  document.addEventListener('pjax:complete', function () {
    LCCounter.refreshCounter();
  });
</script>








<script>
function listennSidebarTOC() {
  const navItems = document.querySelectorAll(".toc li");
  if (!navItems.length) return;
  const sections = [...navItems].map((element) => {
    const link = element.querySelector(".toc-link");
    const target = document.getElementById(
      decodeURI(link.getAttribute("href")).replace("#", "")
    );
    link.addEventListener("click", (event) => {
      event.preventDefault();
      window.scrollTo({
		top: target.offsetTop + 100,
		
		behavior: "smooth"
		
	  });
    });
    return target;
  });

  function activateNavByIndex(target) {
    if (target.classList.contains("active-current")) return;

    document.querySelectorAll(".toc .active").forEach((element) => {
      element.classList.remove("active", "active-current");
    });
    target.classList.add("active", "active-current");
    let parent = target.parentNode;
    while (!parent.matches(".toc")) {
      if (parent.matches("li")) parent.classList.add("active");
      parent = parent.parentNode;
    }
  }

  function findIndex(entries) {
    let index = 0;
    let entry = entries[index];
    if (entry.boundingClientRect.top > 0) {
      index = sections.indexOf(entry.target);
      return index === 0 ? 0 : index - 1;
    }
    for (; index < entries.length; index++) {
      if (entries[index].boundingClientRect.top <= 0) {
        entry = entries[index];
      } else {
        return sections.indexOf(entry.target);
      }
    }
    return sections.indexOf(entry.target);
  }

  function createIntersectionObserver(marginTop) {
    marginTop = Math.floor(marginTop + 10000);
    let intersectionObserver = new IntersectionObserver(
      (entries, observe) => {
        let scrollHeight = document.documentElement.scrollHeight + 100;
        if (scrollHeight > marginTop) {
          observe.disconnect();
          createIntersectionObserver(scrollHeight);
          return;
        }
        let index = findIndex(entries);
        activateNavByIndex(navItems[index]);
      },
      {
        rootMargin: marginTop + "px 0px -100% 0px",
        threshold: 0,
      }
    );
    sections.forEach((element) => {
      element && intersectionObserver.observe(element);
    });
  }
  createIntersectionObserver(document.documentElement.scrollHeight);
}

document.addEventListener("DOMContentLoaded", listennSidebarTOC);
document.addEventListener("pjax:success", listennSidebarTOC);
</script>

<!-- more -->




    
      


<script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js"></script>


<script>
    var pjax;
    document.addEventListener('DOMContentLoaded', function () {
      pjax = new Pjax({
        elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox])',
        selectors: [
          "title",
          "#l_cover",
          "#pjax-container",
          "#pjax-header-nav-list"
        ],
        cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
        timeout: 5000
      });
    });

    document.addEventListener('pjax:send', function (e) {
      //window.stop(); // 相当于点击了浏览器的停止按钮

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = [""];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      window.subData = null; // 移除标题（用于一二级导航栏切换处）
      if (typeof $.fancybox != "undefined") {
        $.fancybox.close();    // 关闭弹窗
      }
      volantis.$switcher.removeClass('active'); // 关闭移动端激活的搜索框
      volantis.$header.removeClass('z_search-open'); // 关闭移动端激活的搜索框
      volantis.$wrapper.removeClass('sub'); // 跳转页面时关闭二级导航

      // 解绑事件 避免重复监听
      volantis.$topBtn.unbind('click');
      $('.menu a').unbind('click');
      $(window).unbind('resize');
      $(window).unbind('scroll');
      $(document).unbind('scroll');
      $(document).unbind('click');
      $('body').unbind('click');
	  
    });

    document.addEventListener('pjax:complete', function () {
      // 关于百度统计对 SPA 页面的处理：
      // 方案一：百度统计>管理>单页应用设置中，打开开启按钮即可对SPA进行统计。 https://tongji.baidu.com/web/help/article?id=324
      // 方案二：取消注释下列代码。 https://tongji.baidu.com/web/help/article?id=235
      // 

      // 关于谷歌统计对 SPA 页面的处理：
      // 当应用以动态方式加载内容并更新地址栏中的网址时，也应该更新通过 gtag.js 存储的网页网址。
      // https://developers.google.cn/analytics/devguides/collection/gtagjs/single-page-applications?hl=zh-cn
      

      $('.nav-main').find('.list-v').not('.menu-phone').removeAttr("style",""); // 移除小尾巴的移除
      $('.menu-phone.list-v').removeAttr("style",""); // 移除小尾巴的移除
      $('script[data-pjax], .pjax-reload script').each(function () {
        $(this).parent().append($(this).remove());
      });
      try{
          if (typeof $.fancybox == "undefined") {
            SCload_fancybox();
          } else {
            pjax_fancybox();
          }
        
        
        
        
        
          pjax_initCopyCode();
        
        
        
        
        
      } catch (e) {
        console.log(e);
      }
	  
    });

    document.addEventListener('pjax:error', function (e) {
	  
      window.location.href = e.triggerElement.href;
    });
</script>

    
  </div>
</body>
</html>
